﻿/*
 * Copyright 2014 Francois Karman
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using Quartz.WebManager.Logic;
using Quartz.WebManager.Model;
using Quartz.WebManager.Web.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Quartz.WebManager.Web.Controllers
{
    /// <summary>
    /// Manages the triggers.
    /// </summary>
    public class TriggerController : Controller
    {
        /// <summary>
        /// Displays the form to add a new trigger to an existing job.
        /// </summary>
        /// <param name="jobName">The name of the job.</param>
        /// <param name="jobGroup">The group of the job.</param>
        /// <returns>The view associated with this page.</returns>
        [HttpGet]
        public ActionResult Add(string jobName, string jobGroup)
        {
            JobKey jobKey = JobKey.Create(jobName, jobGroup);
            JobDetail detail = JobDetailManager.RetrieveOne(jobKey, true);

            if (detail == null)
            {
                throw new ArgumentException("The associated job doesn't exist", "jobName");
            }

            WebTrigger model = new WebTrigger();
            model.JobDetail = detail;
            model.JobGroup = jobGroup;
            model.JobName = jobName;

            return this.View(model);
        }

        /// <summary>
        /// Validates and saves a new trigger.
        /// </summary>
        /// <param name="model">The data of the trigger.</param>
        /// <returns>A redirection to the display of the job; or the form in case of an error.</returns>
        [HttpPost]
        public ActionResult Add(WebTrigger model)
        {
            JobKey jobKey = JobKey.Create(model.JobName, model.JobGroup);
            JobDetail detail = JobDetailManager.RetrieveOne(jobKey, true);

            if (detail == null)
            {
                throw new ArgumentException("The associated job doesn't exist", "model");
            }

            model.JobDetail = detail;
            if (this.ModelState.IsValid)
            {
                // Try to store the data
                try
                {
                    TriggerManager.SaveOne(model);
                }
                catch (ObjectAlreadyExistsException e)
                {
                    this.ModelState.AddModelError("", "A trigger with the same name and group already exist");
                }
            }

            if (this.ModelState.IsValid)
            {
                return this.RedirectToAction("ViewJobDetail", "Home", jobKey);
            }
            else
            {
                return this.View(model);
            }
        }

        /// <summary>
        /// Displays the form to edit a specific trigger.
        /// </summary>
        /// <param name="name">The name of the trigger.</param>
        /// <param name="group">The group of the trigger.</param>
        /// <returns>The view associated with the page.</returns>
        [HttpGet]
        public ActionResult Edit(string name, string group)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }
            else if (string.IsNullOrEmpty(group))
            {
                throw new ArgumentNullException("group");
            }

            TriggerKey triggerKey = new TriggerKey(name, group);
            Trigger current = TriggerManager.RetrieveOne(triggerKey);
            if (current == null)
            {
                throw new ArgumentException("The trigger doesn't exist", "name");
            }

            JobKey jobKey = JobKey.Create(current.JobName, current.JobGroup);
            JobDetail detail = JobDetailManager.RetrieveOne(jobKey, true);
            WebTrigger model = new WebTrigger(current);
            model.JobDetail = detail;

            return this.View(model);
        }

        /// <summary>
        /// Validates and saves a modified trigger.
        /// </summary>
        /// <param name="model">The data of the trigger</param>
        /// <returns>A redirection to the display of the job; or the form in case of an error.</returns>
        [HttpPost]
        public ActionResult Edit(WebTrigger model)
        {
            if (model == null)
            {
                throw new ArgumentNullException("model");
            }

            TriggerKey triggerKey = new TriggerKey(model.Name, model.Group);
            Trigger current = TriggerManager.RetrieveOne(triggerKey);
            if (current == null)
            {
                throw new ArgumentException("The trigger doesn't exist", "model");
            }

            if (current.JobName != model.JobName || current.JobGroup != model.JobGroup)
            {
                throw new ArgumentException("The trigger can't be associated to a new job", "model");
            }

            JobKey jobKey = JobKey.Create(current.JobName, current.JobGroup);
            JobDetail detail = JobDetailManager.RetrieveOne(jobKey, true);
            model.JobDetail = detail;
            if (this.ModelState.IsValid)
            {
                // Try to store the data
                TriggerManager.SaveOne(model, true);
                return this.RedirectToAction("ViewJobDetail", "Home", jobKey);
            }
            else
            {
                return this.View(model);
            }
        }

        /// <summary>
        /// Removes a specific trigger.
        /// </summary>
        /// <param name="name">The name of the trigger.</param>
        /// <param name="group">The group of the trigger.</param>
        /// <returns>A redirection to the display of the job.</returns>
        [HttpGet]
        public ActionResult Remove(string name, string group)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name");
            }
            else if (string.IsNullOrEmpty(group))
            {
                throw new ArgumentNullException("group");
            }

            TriggerKey triggerKey = new TriggerKey(name, group);
            Trigger current = TriggerManager.RetrieveOne(triggerKey);
            if (current == null)
            {
                throw new ArgumentException("The trigger doesn't exist", "name");
            }

            TriggerManager.RemoveOne(triggerKey);
            return this.RedirectToAction("ViewJobDetail", "Home", new { name = current.JobName, group = current.JobGroup });
        }
    }
}
